package com.example.remoteassistance;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

public class StreamWebSocketService extends Service {

    private static final String TAG = "StreamWebSocketService";

    private MediaProjectionManager mMediaProjectionManager;

    public static StreamWebSocketClient mStreamWebSocketClient;
    private final StreamWebSocketBinder mStreamWebSocketBinder = new StreamWebSocketBinder();

    private VideoEncoder mVideoEncoder;

    public class StreamWebSocketBinder extends Binder {
        public StreamWebSocketService getService() {
            return StreamWebSocketService.this;
        }
    }

    VideoEncoder.EncoderListener encoderListener = new VideoEncoder.EncoderListener() {
        @Override
        public void onEncodeData(byte[] bytes) {
            Log.d(TAG, "size:" + (bytes.length / 1024) + "KB");
            try {
                mStreamWebSocketClient.send(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
        Log.d(TAG, "onCreate");
    }

    @Override
    public IBinder onBind(Intent intent) {
        String mid;
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            initRecord(bundle.getInt("code"), bundle.getParcelable("data"));
            mid = bundle.getString("mid");
        } else {
            mid = intent.getStringExtra("mid");
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                initStreamWebSocketClient(mid);
            }
        }).start();
        Log.d(TAG, "onBind");
        return mStreamWebSocketBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeStreamWebSocketClient();
        Log.d(TAG, "onDestroy");
    }

    private void initRecord(int resultCode, Intent resultData) {
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, resultData);
        if (mediaProjection != null) {
            mVideoEncoder = new VideoEncoder(mediaProjection, metrics.widthPixels, metrics.heightPixels);
            mVideoEncoder.setListener(encoderListener);
        }
    }

    public void startRecord() {
        if (mVideoEncoder != null) {
            mVideoEncoder.start();
            Log.d(TAG, "startRecord");
        }
    }

    public void stopRecord() {
        if (mVideoEncoder != null) {
            mVideoEncoder.stop();
            Log.d(TAG, "stopRecord");
        }
    }

    public void destroyRecord() {
        if (mVideoEncoder != null) {
            mVideoEncoder.destroy();
            Log.d(TAG, "destroyRecord");
        }
    }

    public void initStreamWebSocketClient(String mid) {
        URI uri = URI.create(URLUtils.WSURL + mid);
        mStreamWebSocketClient = new StreamWebSocketClient(uri) {
            @Override
            public void onMessage(ByteBuffer byteBuffer) {
                Log.d(TAG, "onByteBuffer");
                byte[] bytes = new byte[byteBuffer.remaining()];
                byteBuffer.get(bytes);
                Intent intent = new Intent();
                intent.setAction("com.example.remoteassistance.websocket.stream");
                intent.putExtra("bytes", bytes);
                sendBroadcast(intent);
            }
        };
        try {
            mStreamWebSocketClient.connectBlocking();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "initStreamWebSocketClient");
    }

    private void closeStreamWebSocketClient() {
        if (mStreamWebSocketClient != null) {
            mStreamWebSocketClient.close();
            Log.d(TAG, "closeStreamWebSocketClient");
        }
    }
}